﻿/* Author: Achim Schnell */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AppFx.Parsing;
using AppFx.Tokenization;

namespace AppFx.Evaluation
{
    /// <summary>
    /// Evaluates RPN-tokens.
    /// </summary>
    public class RpnEvaluator
    {
        #region Methods

        public double EvaluateRpn(IList<IParsedToken> tokens)
        {
            Stack<IParsedToken> stack = new Stack<IParsedToken>();

            int index = 0;
            while (index < tokens.Count)
            {
                IParsedToken token = tokens[index];
                switch (token.ParsedType)
                {
                    case eParsedTokenType.Number:
                        stack.Push(token);
                        break;
                    default:
                        IParsedToken t1 = stack.Pop();
                        IParsedToken t2 = stack.Pop();
                        double v1 = double.Parse(t1.Content);
                        double v2 = double.Parse(t2.Content);
                        double r = 0;
                        if (token.Content == "+")
                            r = v1 + v2;
                        if (token.Content == "-")
                            r = v1 - v2;
                        if (token.Content == "*")
                            r = v1 * v2;
                        if (token.Content == "/")
                            r = v1 / v2;
                        if (token.Content == "^")
                            r = Math.Pow(v1, v2);
                        stack.Push(new ParsedToken(new Token(r.ToString(), eTokenType.NumberLiteral), eParsedTokenType.Number));
                        break;
                }
                index = index + 1;
            }
            if (stack.Count == 1)
                return double.Parse(stack.Pop().Content);
            else
                return 0;
        }

        #endregion
    }
}
